import os
import shutil
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                            QLabel, QPushButton, QListWidget, QListWidgetItem, 
                            QTextEdit, QProgressBar, QFileDialog, QMessageBox, QDialog)
from PyQt5.QtCore import Qt, QStringListModel
from PyQt5.QtGui import QFont, QStandardItemModel, QStandardItem


class FolderSelectionDialog(QDialog):
    """文件夹多选对话框，兼容旧版本PyQt5"""
    def __init__(self, parent=None, caption="选择文件夹", directory=""):
        super().__init__(parent)
        self.setWindowTitle(caption)
        self.resize(600, 400)
        
        self.selected_folders = []
        self.current_dir = directory
        
        # 创建布局
        layout = QVBoxLayout(self)
        
        # 列表显示已选文件夹
        self.list_model = QStringListModel()
        self.list_view = QListWidget()
        layout.addWidget(self.list_view)
        
        # 按钮区
        btn_layout = QHBoxLayout()
        
        self.add_btn = QPushButton("添加文件夹")
        self.add_btn.clicked.connect(self.add_folder)
        btn_layout.addWidget(self.add_btn)
        
        self.remove_btn = QPushButton("移除选中")
        self.remove_btn.clicked.connect(self.remove_folder)
        btn_layout.addWidget(self.remove_btn)
        
        self.ok_btn = QPushButton("确定")
        self.ok_btn.clicked.connect(self.accept)
        btn_layout.addWidget(self.ok_btn)
        
        self.cancel_btn = QPushButton("取消")
        self.cancel_btn.clicked.connect(self.reject)
        btn_layout.addWidget(self.cancel_btn)
        
        layout.addLayout(btn_layout)
    
    def add_folder(self):
        """添加单个文件夹"""
        folder = QFileDialog.getExistingDirectory(
            self, "选择文件夹", self.current_dir
        )
        if folder and folder not in self.selected_folders:
            self.selected_folders.append(folder)
            self.list_view.addItem(folder)
            self.current_dir = folder  # 更新当前目录
    
    def remove_folder(self):
        """移除选中的文件夹"""
        for item in self.list_view.selectedItems():
            row = self.list_view.row(item)
            del self.selected_folders[row]
            self.list_view.takeItem(row)
    
    def get_folders(self):
        """返回选中的文件夹列表"""
        return self.selected_folders


class MultiFolderCopyGUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("多文件夹批量复制工具")
        self.resize(900, 650)
        self.setMinimumSize(800, 600)
        
        # 存储选择的路径
        self.source_files = []  # 源文件列表
        self.source_folders = []  # 源文件夹列表
        self.target_folders = []  # 目标文件夹列表
        
        # 初始化界面
        self.init_ui()
        
        # 当前路径（用于对话框初始目录）
        self.current_path = os.path.dirname(os.path.abspath(__file__))

    def init_ui(self):
        # 主Widget和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)
        main_layout.setContentsMargins(10, 10, 10, 10)
        main_layout.setSpacing(8)
        
        # -------------------------- 1. 源文件选择区域 --------------------------
        # 标题
        file_label = QLabel("1. 选择需要复制的文件 (可多选):")
        file_label.setFont(QFont("微软雅黑", 10, QFont.Bold))
        main_layout.addWidget(file_label)
        
        # 按钮区
        file_btn_layout = QHBoxLayout()
        main_layout.addLayout(file_btn_layout)
        
        self.add_file_btn = QPushButton("添加文件...")
        self.add_file_btn.clicked.connect(self.add_source_files)
        file_btn_layout.addWidget(self.add_file_btn)
        
        self.clear_file_btn = QPushButton("清除全部")
        self.clear_file_btn.clicked.connect(self.clear_source_files)
        file_btn_layout.addWidget(self.clear_file_btn)
        
        # 文件列表
        self.file_list = QListWidget()
        self.file_list.setSelectionMode(QListWidget.ExtendedSelection)  # 支持多选
        self.file_list.setMaximumHeight(80)
        main_layout.addWidget(self.file_list)
        
        # 删除选中文件按钮
        self.del_file_btn = QPushButton("删除选中文件")
        self.del_file_btn.clicked.connect(self.remove_selected_files)
        main_layout.addWidget(self.del_file_btn)
        
        # -------------------------- 2. 源文件夹选择区域 --------------------------
        # 标题
        folder_label = QLabel("2. 选择需要复制的文件夹 (可多选):")
        folder_label.setFont(QFont("微软雅黑", 10, QFont.Bold))
        main_layout.addWidget(folder_label)
        
        # 按钮区
        folder_btn_layout = QHBoxLayout()
        main_layout.addLayout(folder_btn_layout)
        
        self.add_folder_btn = QPushButton("添加文件夹...")
        self.add_folder_btn.clicked.connect(self.add_source_folders)
        folder_btn_layout.addWidget(self.add_folder_btn)
        
        self.clear_folder_btn = QPushButton("清除全部")
        self.clear_folder_btn.clicked.connect(self.clear_source_folders)
        folder_btn_layout.addWidget(self.clear_folder_btn)
        
        # 文件夹列表
        self.folder_list = QListWidget()
        self.folder_list.setSelectionMode(QListWidget.ExtendedSelection)
        self.folder_list.setMaximumHeight(80)
        main_layout.addWidget(self.folder_list)
        
        # 删除选中文件夹按钮
        self.del_folder_btn = QPushButton("删除选中文件夹")
        self.del_folder_btn.clicked.connect(self.remove_selected_folders)
        main_layout.addWidget(self.del_folder_btn)
        
        # -------------------------- 3. 目标文件夹选择区域 --------------------------
        # 标题
        target_label = QLabel("3. 选择目标文件夹 (可多选):")
        target_label.setFont(QFont("微软雅黑", 10, QFont.Bold))
        main_layout.addWidget(target_label)
        
        # 按钮区
        target_btn_layout = QHBoxLayout()
        main_layout.addLayout(target_btn_layout)
        
        self.add_target_btn = QPushButton("添加目标文件夹...")
        self.add_target_btn.clicked.connect(self.add_target_folders)
        target_btn_layout.addWidget(self.add_target_btn)
        
        self.clear_target_btn = QPushButton("清除全部")
        self.clear_target_btn.clicked.connect(self.clear_target_folders)
        target_btn_layout.addWidget(self.clear_target_btn)
        
        # 目标文件夹列表
        self.target_list = QListWidget()
        self.target_list.setSelectionMode(QListWidget.ExtendedSelection)
        self.target_list.setMaximumHeight(80)
        main_layout.addWidget(self.target_list)
        
        # 删除选中目标文件夹按钮
        self.del_target_btn = QPushButton("删除选中目标文件夹")
        self.del_target_btn.clicked.connect(self.remove_selected_targets)
        main_layout.addWidget(self.del_target_btn)
        
        # -------------------------- 操作按钮区 --------------------------
        op_btn_layout = QHBoxLayout()
        main_layout.addLayout(op_btn_layout)
        
        self.start_btn = QPushButton("开始复制")
        self.start_btn.setFont(QFont("微软雅黑", 9, QFont.Bold))
        self.start_btn.setStyleSheet("background-color: #4CAF50; color: white;")
        self.start_btn.clicked.connect(self.start_copy)
        op_btn_layout.addWidget(self.start_btn)
        
        self.clear_log_btn = QPushButton("清除日志")
        self.clear_log_btn.clicked.connect(self.clear_log)
        op_btn_layout.addWidget(self.clear_log_btn)
        
        # -------------------------- 进度条 --------------------------
        progress_label = QLabel("复制进度:")
        main_layout.addWidget(progress_label)
        
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(0)
        main_layout.addWidget(self.progress_bar)
        
        # -------------------------- 日志区域 --------------------------
        log_label = QLabel("操作日志:")
        main_layout.addWidget(log_label)
        
        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)  # 只读
        self.log_text.setMinimumHeight(100)
        main_layout.addWidget(self.log_text)

    # -------------------------- 源文件操作 --------------------------
    def add_source_files(self):
        """添加源文件（支持多选）"""
        files, _ = QFileDialog.getOpenFileNames(
            self, "选择要复制的文件", self.current_path, "所有文件 (*)"
        )
        if files:
            for file in files:
                if file not in self.source_files:
                    self.source_files.append(file)
                    self.file_list.addItem(file)  # 列表中添加项
            self.current_path = os.path.dirname(files[0])  # 更新初始目录

    def clear_source_files(self):
        """清除所有源文件"""
        self.source_files.clear()
        self.file_list.clear()

    def remove_selected_files(self):
        """删除选中的源文件"""
        for item in self.file_list.selectedItems():
            row = self.file_list.row(item)
            del self.source_files[row]
            self.file_list.takeItem(row)

    # -------------------------- 源文件夹操作 --------------------------
    def add_source_folders(self):
        """添加源文件夹（支持多选）"""
        dialog = FolderSelectionDialog(
            self, "选择要复制的文件夹", self.current_path
        )
        if dialog.exec_():
            folders = dialog.get_folders()
            if folders:
                for folder in folders:
                    if folder not in self.source_folders:
                        self.source_folders.append(folder)
                        self.folder_list.addItem(folder)
                self.current_path = os.path.dirname(folders[0])  # 更新初始目录

    def clear_source_folders(self):
        """清除所有源文件夹"""
        self.source_folders.clear()
        self.folder_list.clear()

    def remove_selected_folders(self):
        """删除选中的源文件夹"""
        for item in self.folder_list.selectedItems():
            row = self.folder_list.row(item)
            del self.source_folders[row]
            self.folder_list.takeItem(row)

    # -------------------------- 目标文件夹操作 --------------------------
    def add_target_folders(self):
        """添加目标文件夹（支持多选）"""
        dialog = FolderSelectionDialog(
            self, "选择目标文件夹", self.current_path
        )
        if dialog.exec_():
            folders = dialog.get_folders()
            if folders:
                for folder in folders:
                    if folder not in self.target_folders:
                        self.target_folders.append(folder)
                        self.target_list.addItem(folder)
                self.current_path = os.path.dirname(folders[0])  # 更新初始目录

    def clear_target_folders(self):
        """清除所有目标文件夹"""
        self.target_folders.clear()
        self.target_list.clear()

    def remove_selected_targets(self):
        """删除选中的目标文件夹"""
        for item in self.target_list.selectedItems():
            row = self.target_list.row(item)
            del self.target_folders[row]
            self.target_list.takeItem(row)

    # -------------------------- 日志和进度条 --------------------------
    def log(self, message):
        """添加日志信息"""
        self.log_text.append(message)
        # 自动滚动到底部
        self.log_text.moveCursor(self.log_text.textCursor().End)

    def clear_log(self):
        """清除日志"""
        self.log_text.clear()

    # -------------------------- 核心复制功能 --------------------------
    def start_copy(self):
        """开始复制操作"""
        # 验证输入
        if not self.source_files and not self.source_folders:
            QMessageBox.critical(self, "错误", "请至少选择一个文件或文件夹进行复制！")
            return
        if not self.target_folders:
            QMessageBox.critical(self, "错误", "请至少选择一个目标文件夹！")
            return

        # 准备所有要复制的项
        items_to_copy = []
        items_to_copy.extend(self.source_files)
        items_to_copy.extend(self.source_folders)
        
        total_items = len(items_to_copy)
        total_targets = len(self.target_folders)
        total_operations = total_items * total_targets  # 总操作数（用于进度计算）
        completed = 0  # 已完成操作数

        self.log("===== 开始复制操作 =====")
        self.log(f"待复制项: {total_items} 个（文件: {len(self.source_files)}, 文件夹: {len(self.source_folders)}）")
        self.log(f"目标文件夹: {total_targets} 个")

        # 遍历所有目标文件夹
        for target_idx, target_folder in enumerate(self.target_folders, 1):
            self.log(f"\n处理目标文件夹 {target_idx}/{total_targets}: {target_folder}")
            
            # 遍历所有待复制项
            for item_idx, item in enumerate(items_to_copy, 1):
                item_name = os.path.basename(item)
                target_path = os.path.join(target_folder, item_name)

                try:
                    # 确保目标目录存在
                    os.makedirs(os.path.dirname(target_path), exist_ok=True)

                    if os.path.isfile(item):
                        # 复制文件（保留元数据）
                        shutil.copy2(item, target_path)
                        self.log(f"  文件 {item_idx}/{total_items}: {item_name} [复制成功]")
                    elif os.path.isdir(item):
                        # 复制文件夹（递归）
                        if not os.path.exists(target_path):
                            shutil.copytree(item, target_path)
                            self.log(f"  文件夹 {item_idx}/{total_items}: {item_name} [复制成功]")
                        else:
                            self.log(f"  文件夹 {item_idx}/{total_items}: {item_name} [已存在，跳过]")
                    else:
                        self.log(f"  未知类型 {item_idx}/{total_items}: {item_name} [跳过]")

                except Exception as e:
                    self.log(f"  错误 {item_idx}/{total_items}: {item_name} → {str(e)}")

                # 更新进度
                completed += 1
                progress = int((completed / total_operations) * 100)
                self.progress_bar.setValue(progress)
                QApplication.processEvents()  # 刷新界面

        self.log("\n===== 操作完成 =====")
        QMessageBox.information(self, "完成", "所有复制操作已完成！")
        self.progress_bar.setValue(100)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    # 确保中文显示正常
    font = QFont("SimHei")
    app.setFont(font)
    window = MultiFolderCopyGUI()
    window.show()
    sys.exit(app.exec_())
